#include <stdio.h>
#include <Windows.h>
#include <conio.h>


#define CHECKBOARDSIZE 19			//棋盘大小
int g_checkboard[CHECKBOARDSIZE][CHECKBOARDSIZE] = {0};				//棋盘对局的数据
int g_currentGamer;			//1表示黑子，2表示白子
int g_cursorX,g_cursorY;		//当前光标的位置
int g_count = 0;			//游戏回合数
int g_forbid = 0;			//禁手判断
int g_livethreenum = 3;		//活3
int g_livefournum = 4;		//活4

//运行游戏
int RunGame();
//初始化棋盘
void Init();
//绘制棋盘
void DrawCheckBoard();
//布子,成功返回1，失败返回0
int Put();
//向上检查棋子
int HorizontalCheck();
//向下检查棋子
int VerticalCheck();
//向正斜向检查棋子
int PositiveCheck();
//向反斜向检查棋子
int NegtiveCheck();
//判断输赢
int Judge();
//判断禁手
int Forbidden();
//判断长链禁手
int Overline();
//判断活3的数量
int LineThree();
//判断活4的数量
int LineFour();
//判断冲四的数量
int ChongFour();

int main()
{
	SetConsoleTitle("五子棋对战");
	system("color E0");
	system("mode con cols=40 lines=20");
	//进入游戏
	while (1)
	{
		//运行游戏
		RunGame();

	}
	return 0;
}

//清屏
/*void cls()
{
	COORD pos;
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	for (int i = 0; i < 50; i++) {
		for (int j = 0; j < 50; j++)
			putchar(' ');
		puts(" ");
	}
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(hOut, pos);
}*/


//进行整个对局，返回赢家信息
int RunGame()
{
	Init();		//初始化
	int input = 0;		//键盘输入值
	int player = 0;		//玩家
	int forbid = 0;		//禁手
	int count = 0;		//落子数
	while (1)
	{
		//清屏
		system("cls");
	//	clear();
		//绘制棋盘
		DrawCheckBoard();
		//获取键盘输入
		input=_getch();
		switch (input)
		{
		case 32:		//空格键落子
		{
			//1.下子->能不能下子
			if (Put())
			{
				++count;
				if (g_currentGamer == 1)
					forbid = Forbidden();		
				//2.判断输赢
				player = Judge();
				//3.更换玩家
				g_currentGamer = 3 - g_currentGamer;
				if (player == 1)
				{
					MessageBox(NULL, "黑子赢了", "五子棋", MB_OK);
					Init();
					DrawCheckBoard();
				}
				else if (g_currentGamer == 2 && player == 0 && forbid == 1)
				{
					MessageBox(NULL, "黑子输了", "五子棋", MB_OK);
					Init();
					DrawCheckBoard();
				} 
				else if (player == 2)
				{
					MessageBox(NULL, "白子赢了", "五子棋", MB_OK);
					Init();
					DrawCheckBoard();
				}
				//平局判断
				else if (count >= CHECKBOARDSIZE*CHECKBOARDSIZE)
				{
					MessageBox(NULL, "平局", "五子棋", MB_OK);
					Init();
					DrawCheckBoard();
				}
				
			}
			else
			{
				MessageBox(NULL, "此处不能落子", "五子棋", MB_OK);
			}
		}
		case 75:		//向上
			g_cursorY--;
			break;
		case 77:		//向下
			g_cursorY++;
			break;
		case 72:		//向左
			g_cursorX--;
			break;
		case 80:		//向右
			g_cursorX++;
			break;
		default:
			break;
		}
		if (g_cursorY < 0)
			g_cursorY = CHECKBOARDSIZE - 1;
		else if (g_cursorY > CHECKBOARDSIZE - 1)
			g_cursorY = 0;
		if (g_cursorX < 0)
			g_cursorX = CHECKBOARDSIZE - 1;
		else if (g_cursorX > CHECKBOARDSIZE - 1)
			g_cursorX = 0;
	}
	return 0;
}

//初始化
void Init()
{
	//清空二维数组
	memset(g_checkboard, 0, sizeof(g_checkboard));
	g_currentGamer = 1;		//黑子
	//光标位置
	g_cursorX = CHECKBOARDSIZE / 2;		
	g_cursorY = CHECKBOARDSIZE / 2;
	g_count = 0;

}

//绘制棋盘
void DrawCheckBoard()
{
	for (int i = 0; i < CHECKBOARDSIZE; i++)		//行
	{
		for (int j = 0; j < CHECKBOARDSIZE; j++)	//列
		{
			if (i == g_cursorX && j == g_cursorY)
				printf("╬ ");
			else if (g_checkboard[i][j] == 1)
				printf("●");
			else if (g_checkboard[i][j] == 2)
				printf("○");
			else if (i == 0 && j == 0)
				printf("┏ ");
			else if (i == 0 && j == CHECKBOARDSIZE - 1)
				printf("┓ ");
			else if (i == CHECKBOARDSIZE - 1 && j == 0)
				printf("┗ ");
			else if (i == CHECKBOARDSIZE - 1 && j == CHECKBOARDSIZE - 1)
				printf("┛ ");
			else if (i == 0)
				printf("┬ ");
			else if (i == CHECKBOARDSIZE - 1)
				printf("┴ ");
			else if (j == 0)
				printf("├ ");
			else if (j == CHECKBOARDSIZE - 1)
				printf("┤ ");
			else
				printf("┼ ");
		}
		printf("\n");
	}
}

//布子,成功返回1，失败返回0
int Put()
{
	//下子成功，并且该下哪颗子
	if (g_checkboard[g_cursorX][g_cursorY] == 0)
	{
		g_checkboard[g_cursorX][g_cursorY] = g_currentGamer;
		return 1;
	}
	else
		return 0;
}

/***********************************检查棋子连线******************************************/
//检查棋子
int HorizontalCheck()
{
	int Horizontal = 1;		//水平方向

	//水平方向
	//向右检查
	for (int i = 1; i < 5; i++)
	{
		if (g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX][g_cursorY + i] == g_currentGamer)
			Horizontal++;
		else
			break;
	}
	//向左检查
	for (int i = 1; i < 5; i++)
	{
		if (g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX][g_cursorY - i] == g_currentGamer)
			Horizontal++;
		else
			break;
	}
	return Horizontal;
}

//垂直方向
int VerticalCheck()
{
	//向上检查
	int Vertical = 1;		//垂直方向
	for (int i = 1; i < 5; i++)
	{
		if (g_cursorX + i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY] == g_currentGamer)
			Vertical++;
		else
			break;
	}
	//向左检查
	for (int i = 1; i < 5; i++)
	{
		if (g_cursorX - i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY] == g_currentGamer)
			Vertical++;
		else
			break;
	}
	return Vertical;
}

//正斜方向
int PositiveCheck()
{
	int PositiveDirection = 1;		//正斜向
	//向上
	for (int i = 1; i < 5; i++)
	{
		if (g_cursorX - i < CHECKBOARDSIZE && g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY - i] == g_currentGamer)
			PositiveDirection++;
		else
			break;
	}
	//向下
	for (int i = 1; i < 5; i++)
	{
		if (g_cursorX + i < CHECKBOARDSIZE && g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY + i] == g_currentGamer)
			PositiveDirection++;
		else
			break;
	}
	return PositiveDirection;
}

//反斜方向
int NegtiveCheck()
{
	int NegtiveDirection = 1;		//反斜向
	//向上
	for (int i = 1; i < 5; i++)
	{
		if (g_cursorX - i < CHECKBOARDSIZE && g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY + i] == g_currentGamer)
			NegtiveDirection++;
		else
			break;
	}
	//向下
	for (int i = 1; i < 5; i++)
	{
		if (g_cursorX + i < CHECKBOARDSIZE && g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY - i] == g_currentGamer)
			NegtiveDirection++;
		else
			break;
	}
	return NegtiveDirection;
}

//判断输赢
int Judge()
{
	int Horizontal;		//水平方向
	int Vertical;		//垂直方向
	int PositiveDirection;		//正斜向
	int NegtiveDirection;		//反斜向

	Horizontal = HorizontalCheck();
	if (Horizontal >= 5)
		return g_currentGamer;
//	else
//		return Horizontal;

	Vertical = VerticalCheck();
	if (Vertical >= 5)
		return g_currentGamer;
//	else
//		return Vertical;

	PositiveDirection = PositiveCheck();
	if (PositiveDirection >= 5)
		return g_currentGamer;
//	else
//		return PositiveDirection;

	NegtiveDirection = NegtiveCheck();
	if (NegtiveDirection >= 5)
		return g_currentGamer;
//	else
//		return NegtiveDirection;
	return 0;
}
/************************************判断禁手***************************************/
//判断禁手
int Forbidden()
{
	int flagoverline;	//长连
	int live3;			//活3
	int live4;			//活4
	int chong4;			//冲4

	flagoverline = Overline();
	if (flagoverline)
		return 1;

	live3 = LineThree();
	if (live3)
		return 1;
	return 0;
}

//判断长链禁手
int Overline()
{
	int Horizontal;		//水平方向
	int Vertical;		//垂直方向
	int PositiveDirection;		//正斜向
	int NegtiveDirection;		//反斜向

	Horizontal = HorizontalCheck();
	if (Horizontal > 5)
		return 1;

	Vertical = VerticalCheck();
	if (Vertical > 5)
		return 1;

	PositiveDirection = PositiveCheck();
	if (PositiveDirection > 5)
		return 1;

	NegtiveDirection = NegtiveCheck();
	if (NegtiveDirection > 5)
		return 1;
	return 0;
}

//判断活3的数量
int LineThree()
{
	int rightnum=0,leftnum = 0,horizontal=1;
	int upnum = 0, downnum = 0, vertical = 1;
	int posupnum = 0, posdownnum = 0, positive = 1;
	int negupnum = 0, negdownnum = 0, negtive = 1;
	int num = 0;
//水平检查
	//向右检查
	for (int i = 1; i < 6; i++)
	{
		if (g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX][g_cursorY + i] == g_currentGamer)
			++rightnum;
		else if (g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX][g_cursorY + i] == g_forbid)
			break;
	}
	//向左检查
	for (int i = 1; i < 6; i++)
	{
		if (g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX][g_cursorY - i] == g_currentGamer)
			++leftnum;
		else if (g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX][g_cursorY - i] == g_forbid)
			break;
	}
	horizontal += leftnum + rightnum;
	if (horizontal == 3)
		++num;
//垂直检查
	//向上检查
	int Vertical = 1;		//垂直方向
	for (int i = 1; i < 6; i++)
	{
		if (g_cursorX + i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY] == g_currentGamer)
			++upnum;
		else if (g_cursorX + i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY] == g_forbid)
			break;
	}
	//向下检查
	for (int i = 1; i < 6; i++)
	{
		if (g_cursorX - i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY] == g_currentGamer)
			++downnum;
		else if (g_cursorX - i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY] == g_forbid)
			break;
	}
	vertical += upnum + downnum;
	if (vertical == 3)
		++num;
//正斜检查
	//向上
	for (int i = 1; i < 6; i++)
	{
		if (g_cursorX - i < CHECKBOARDSIZE && g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY - i] == g_currentGamer)
			++posupnum;
		else if (g_cursorX - i < CHECKBOARDSIZE && g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY - i] == g_forbid)
			break;
	}
	//向下
	for (int i = 1; i < 6; i++)
	{
		if (g_cursorX + i < CHECKBOARDSIZE && g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY + i] == g_currentGamer)
			++posdownnum;
		else if (g_cursorX + i < CHECKBOARDSIZE && g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY + i] == g_forbid)
			break;
	}
	positive += posdownnum + posupnum;
	if (posdownnum == 3)
		++num;
//反斜检查
	//向上
	for (int i = 1; i < 6; i++)
	{
		if (g_cursorX - i < CHECKBOARDSIZE && g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY + i] == g_currentGamer)
			++negupnum;
		else if (g_cursorX - i < CHECKBOARDSIZE && g_cursorY + i < CHECKBOARDSIZE && g_checkboard[g_cursorX - i][g_cursorY + i] == g_forbid)
			break;
	}
	//向下
	for (int i = 1; i < 6; i++)
	{
		if (g_cursorX + i < CHECKBOARDSIZE && g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY - i] == g_currentGamer)
			++negdownnum;
		else if (g_cursorX + i < CHECKBOARDSIZE && g_cursorY - i < CHECKBOARDSIZE && g_checkboard[g_cursorX + i][g_cursorY - i] == g_forbid)
			break;
	}
	negtive += negupnum + negdownnum;
	if (negtive == 3)
		++num;
	if (num >= 2)
		return 1;
	return 0;
}

//判断活4的数量
int LineFour()
{
	return 0;
}
